package com.nus.fellowmark.modules.assignment.service.impl;

import com.nus.fellowmark.common.mongo.service.MongoFileService;
import com.nus.fellowmark.dao.SubmissionDao;
import com.nus.fellowmark.entity.PairingEntity;
import com.nus.fellowmark.entity.SubmissionEntity;
import com.nus.fellowmark.modules.assignment.constant.Constant;
import com.nus.fellowmark.modules.assignment.constant.PairConstant;
import com.nus.fellowmark.modules.assignment.dto.UploadSubmissionDTO;
import com.nus.fellowmark.modules.assignment.service.PairingService;
import com.nus.fellowmark.modules.assignment.service.SubmissionService;
import com.nus.fellowmark.modules.assignment.vo.MarkTaskVO;
import com.nus.fellowmark.modules.assignment.vo.SubmissionVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nus.fellowmark.common.utils.PageUtils;
import com.nus.fellowmark.common.utils.Query;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author Ruoyi Chen
 * @email chenruoyisz@gmail.com
 * @create 2023-02-27
 */
@Service("submissionService")
public class SubmissionServiceImpl extends ServiceImpl<SubmissionDao, SubmissionEntity> implements SubmissionService {

    @Autowired
    MongoFileService mongoFileService;

    @Autowired
    PairingService pairingService;

    @Autowired
    SubmissionDao submissionDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SubmissionEntity> page = this.page(
                new Query<SubmissionEntity>().getPage(params),
                new QueryWrapper<SubmissionEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public SubmissionVO upload(UploadSubmissionDTO uploadSubmissionDTO) {
        SubmissionEntity submission = getByStuAndAsg(uploadSubmissionDTO.getStudentId(), uploadSubmissionDTO.getAssignmentId());
        if (submission != null) {
            SubmissionVO result = new SubmissionVO();
            result.setSubmissionFileKey(Constant.FILE_EXIST);
            return result;
        }

        MultipartFile file = uploadSubmissionDTO.getFile();
        // 1. upload file to mongo db
        String fileName = uploadSubmissionDTO.getModuleId() + "-"
                + uploadSubmissionDTO.getAssignmentId() + "-"
//                + uploadSubmissionDTO.getQuestionId() + "-"
                + uploadSubmissionDTO.getStudentId() + "-"
                + file.getOriginalFilename();
        String fileKey = mongoFileService.uploadFileWithName(file, fileName);
        if (fileKey == null) {
            return null;
        }

        // 2. save record into mysql
        SubmissionEntity submissionEntity = new SubmissionEntity();
        submissionEntity.setSubmittedByStudentId(uploadSubmissionDTO.getStudentId());
        submissionEntity.setAssignmentId(uploadSubmissionDTO.getAssignmentId());
//        submissionEntity.setQuestionId(uploadSubmissionDTO.getQuestionId());
//        submissionEntity.setContent(uploadSubmissionDTO.getContent());
        submissionEntity.setContentFileLoc(fileKey);
        boolean save = this.save(submissionEntity);

        // 3. return mongo fileKey and fileName for students as submit credentials
        SubmissionVO submissionVO = new SubmissionVO();
        submissionVO.setSubmissionFileKey(fileKey);
        submissionVO.setFileName(fileName);
        return submissionVO;
    }

    @Override
    public List<MarkTaskVO> getAssignedTasks(Integer studentId) {
        // 1. use studentId, to find pairs where markerId == studentId
        List<PairingEntity> pairs = pairingService.listPairsByMarkerId(studentId);

        // 2. for all the pairs, get the submissionIds and submissionFileKeys
        List<MarkTaskVO> markTasks = new ArrayList<>();
        for (PairingEntity pair : pairs) {
            List<SubmissionEntity> submissionEntities = this.list(new QueryWrapper<SubmissionEntity>().eq("submitted_by_student_id", pair.getStudentId())
                    .and(wrapper -> wrapper.eq("assignment_id", pair.getAssignmentId())));
            for (SubmissionEntity submission : submissionEntities) {
                MarkTaskVO markTaskVO = new MarkTaskVO();
                markTaskVO.setPairId(pair.getId());
                markTaskVO.setAssignmentId(pair.getAssignmentId());
                markTaskVO.setActive(pair.getActive());
//                markTaskVO.setQuestionId(submission.getQuestionId());
                markTaskVO.setSubmissionId(submission.getId());
                markTaskVO.setFileKey(submission.getContentFileLoc());
//                markTaskVO.setContent(submission.getContent());
                markTasks.add(markTaskVO);
            }
        }
        return markTasks;
    }

    @Override
    public List<MarkTaskVO> getFeedback(Integer studentId, Integer assignmentId) {
        // 1. use studentId and assignmentId to find pairs
        List<PairingEntity> pairs = pairingService.listPairsByStuAndAsgId(studentId, assignmentId);

        // 2. for all the pairs, get the submissionIds and submissionFileKeys
        List<MarkTaskVO> markTasks = new ArrayList<>();
        for (PairingEntity pair : pairs) {
            List<SubmissionEntity> submissionEntities = this.list(new QueryWrapper<SubmissionEntity>().eq("submitted_by_student_id", pair.getStudentId())
                    .and(wrapper -> wrapper.eq("assignment_id", pair.getAssignmentId())));
            for (SubmissionEntity submission : submissionEntities) {
                MarkTaskVO markTaskVO = new MarkTaskVO();
                markTaskVO.setPairId(pair.getId());
                markTaskVO.setAssignmentId(pair.getAssignmentId());
                markTaskVO.setActive(pair.getActive());
//                markTaskVO.setQuestionId(submission.getQuestionId());
                markTaskVO.setSubmissionId(submission.getId());
                markTaskVO.setFileKey(submission.getContentFileLoc());
//                markTaskVO.setContent(submission.getContent());
                markTasks.add(markTaskVO);
            }
        }
        return markTasks;
    }

    @Override
    public SubmissionEntity getByStuAndAsg(Integer studentId, Integer assignmentId) {
        QueryWrapper<SubmissionEntity> queryWrapper = new QueryWrapper<SubmissionEntity>().eq("submitted_by_student_id", studentId);
        queryWrapper.eq("assignment_id", assignmentId);
        return submissionDao.selectOne(queryWrapper);
    }

}
